<?php

namespace DreamCat\Array2Class\TestCases;

use DreamCat\Array2Class\Array2ClassConverter;
use DreamCat\Array2Class\Demo\DemoFunc;
use DreamCat\Array2Class\Demo\Inner\Pojo3;
use DreamCat\Array2Class\Demo\Inner\Status;
use DreamCat\Array2Class\Demo\Pojo1;
use DreamCat\Array2Class\Demo\Pojo2;
use DreamCat\Array2Class\Demo\PojoAllow;
use DreamCat\Array2Class\Demo\WithStaticPo;
use DreamCat\Array2Class\Exception\ConvertFailed;
use DreamCat\Array2Class\PlainOBjectFactory;
use PHPUnit\Framework\TestCase;
use ReflectionMethod;

/**
 * 异常测试
 * @author vijay
 */
class ErrorTest extends TestCase
{
    /**
     * 测试类不存在的异常
     * @param array $data 输入数据
     * @param string $className 期望输出类
     * @param string $msg 期望异常信息
     * @param array $config 转换器配置
     * @return void
     * @dataProvider errorData
     */
    public function testClassNotExists(array $data, string $className, string $msg, array $config = [])
    {
        $this->expectException(ConvertFailed::class);
        $this->expectExceptionMessage($msg);
        $convert = new Array2ClassConverter();
        foreach ($config as $key => $val) {
            $fn = "set{$key}";
            $convert->$fn($val);
        }

        $convert->convert($data, $className);
    }

    /**
     * 错误的测试数据
     * @return array
     */
    public static function errorData(): array
    {
        return [
            [
                [],
                "notE",
                "指定的输出类型 notE 不存在",
            ],
            [
                [],
                WithStaticPo::class,
                "指定的输出类" . WithStaticPo::class . "构造函数需要参数且未实现接口" . PlainOBjectFactory::class,
                ["tryConstructWithParam" => false],
            ],
            [
                [],
                Pojo3::class,
                Pojo3::class . "::name是必填属性但是未赋值",
            ],
            [
                ["ary" => 3],
                Pojo2::class,
                Pojo2::class . "::ary 要求数组而传入非数组",
            ],
            [
                ["status" => 2],
                Pojo2::class,
                Status::class . "是枚举类型而输入数据不合法",
            ],
            [
                ["p3s" => ["abc"]],
                Pojo1::class,
                Pojo3::class . "无法使用非数组构建",
            ],
            [
                ["union" => []],
                PojoAllow::class,
                PojoAllow::class . "::union 无法转换\n" .
                Pojo1::class . " 转换失败 " . Pojo1::class . "::pojo2是必填属性但是未赋值\n"
                . "string 转换失败 " . PojoAllow::class . "::union 输入参数不是预期的 string\n"
                . "int 转换失败 " . PojoAllow::class . "::union 输入参数不是预期的 int",
            ],
        ];
    }

    /**
     * 测试类不存在的异常
     * @return void
     */
    public function testErrorClassAry()
    {
        $hasError = false;
        try {
            $convert = new Array2ClassConverter();
            $methodRef = new ReflectionMethod(DemoFunc::class, "f");
            $params = $methodRef->getParameters();
            $data = [mt_rand(0, 34)];
            $param = $params[5];
            $convert->convertByType($data, $param->getType(), $param->getAttributes());
        } catch (ConvertFailed $convertFailed) {
            $hasError = true;
            self::assertEquals("类 noClass 不存在，无法转换", $convertFailed->getMessage());
        }
        self::assertTrue($hasError);
    }
}

# end of file
